package com.zjsru.plan2024.oneday;

/**
 * 2129. 将标题首字母大写
 * 如果单词的长度为 1 或者 2 ，所有字母变成小写。
 * 否则，将单词首字母大写，剩余字母变成小写。
 * @Author: cookLee
 * @Date: 2024-03-11
 */
public class CapitalizeTitle {

    /**
     * 主
     * \
     * 输入：title = "capiTalIze tHe titLe"
     * 输出："Capitalize The Title"
     * 解释：
     * 由于所有单词的长度都至少为 3 ，将每个单词首字母大写，剩余字母变为小写。
     * \
     * 输入：title = "First leTTeR of EACH Word"
     * 输出："First Letter of Each Word"
     * 解释：
     * 单词 "of" 长度为 2 ，所以它保持完全小写。
     * 其他单词长度都至少为 3 ，所以其他单词首字母大写，剩余字母小写。
     * \
     * 输入：title = "i lOve leetcode"
     * 输出："i Love Leetcode"
     * 解释：
     * 单词 "i" 长度为 1 ，所以它保留小写。
     * 其他单词长度都至少为 3 ，所以其他单词首字母大写，剩余字母小写
     * \
     * @param args args
     */
    public static void main(String[] args) {
        CapitalizeTitle capitalizeTitle = new CapitalizeTitle();
        String title = "capiTalIze tHe titLe";
        System.out.println(capitalizeTitle.capitalizeTitle3(title));
    }

    /**
     * 常量 字符串空格
     */
    final String CONSTANT_STRING_SPACE = " ";

    /**
     * 常量 空格
     */
    final char CONSTANT_CHAR_SPACE = ' ';

    /**
     * 常量 字母小写a
     */
    final char CONSTANT_CHAR_A = 'a';

    /**
     * 常量ascii大小写字母间隔量
     */
    final Integer CONSTANT_ASCII_PARAM = 32;

    /**
     * 标题大写
     * 字符串模拟
     * @param title 标题
     * @return {@link String}
     */
    public String capitalizeTitle(String title) {
        String[] parts = title.split(this.CONSTANT_STRING_SPACE);
        for (int i = 0; i < parts.length; i ++) {
            String part = parts[i];
            if (part.length() < 3) {
                parts[i] = part.toLowerCase();
            } else {
                parts[i]  = this.helper(part);
            }
        }
        return String.join(this.CONSTANT_STRING_SPACE, parts);
    }

    /**
     * 大写字母转换助手类
     *
     * @param part 零件
     * @return {@link String}
     */
    private String helper(String part) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < part.length(); i++) {
            if (i == 0) {
                sb.append(Character.toUpperCase(part.charAt(i)));
            } else {
                sb.append(Character.toLowerCase(part.charAt(i)));
            }
        }
        return sb.toString();
    }

    /**
     * 标题大写方法2:减少遍历次数
     *
     * @param title 标题
     * @return {@link String}
     */
    public String capitalizeTitle2(String title) {
        title = title.toLowerCase();
        char[] chars = title.toCharArray();
        int start = 0;
        //end表示空格所在位置;start初始化0,即第一个单词的首字母，后续即是下一次个单词的首字母;end重新指向下一个单词的首字母
        for (int end = title.indexOf(this.CONSTANT_CHAR_SPACE); end != -1; start = end + 1, end = title.indexOf(this.CONSTANT_CHAR_SPACE, start)) {
            //判断是否要首字母大写,因为前面已经将字符串全部小写
            if (end - start > 2) {
                chars[start] = Character.toUpperCase(chars[start]);
            }
        }
        //最后一个单词判断首字母是否大写
        if (chars.length - start > 2) {
            chars[start] = Character.toUpperCase(chars[start]);
        }
        return new String(chars);
    }

    /**
     * 双指针：时间损耗最少
     *
     * @param title 标题
     * @return {@link String}
     */
    public String capitalizeTitle3(String title) {
        char[] ans = title.toCharArray();
        int n = ans.length;
        int i = 0, j = 0;
        while (j <= n) {
            //碰到空格和到最后一个字符时
            if (j == n || ans[j] == this.CONSTANT_CHAR_SPACE) {
                //判断首字母是否大写
                if (j - i > 2) {
                    ans[i] -= this.CONSTANT_ASCII_PARAM;
                }
                //重新定位i坐标，放到下一单词开头
                i = j + 1;
                //没碰到空格,将大写字母转化为小写
            } else if (ans[j] < this.CONSTANT_CHAR_A) {
                ans[j] += this.CONSTANT_ASCII_PARAM;
            }
            j++;
        }
        return new String(ans);
    }


}
